package auth

import (
	"car_rental/auth/api/gen/v1"
	"car_rental/auth/dao"
	"context"
	"go.uber.org/zap"
	"google.golang.org/grpc/codes"
	"google.golang.org/grpc/status"
	"time"
)

type Service struct {
	OpenIDResolver
	TokenGenerator
	TokenExpire time.Duration
	*dao.Mongo
	*zap.Logger
}

// OpenIDResolver 处理微信认证code变为OpenId
// https://developers.weixin.qq.com/miniprogram/dev/framework/open-ability/login.html
type OpenIDResolver interface {
	Resolve(code string) (string, error)
}

// TokenGenerator JWT Token生成
type TokenGenerator interface {
	GenerateToken(accountId string, expire time.Duration) (string, error)
}

// Login 登录
func (s *Service) Login(c context.Context, req *authpb.LoginRequest) (*authpb.LoginResponse, error) {

	// 处理微信认证code变为Openid
	openID, err := s.OpenIDResolver.Resolve(req.Code)

	if err != nil {
		return nil, status.Errorf(codes.Unavailable,
			"无法处理openid: %v", err)
	}

	accountId, err := s.Mongo.ResolveAccountId(c, openID)

	if err != nil {
		s.Logger.Error("无法处理用户ID", zap.Error(err))
		return nil, status.Error(codes.Internal, "")
	}

	tkn, err := s.TokenGenerator.GenerateToken(accountId.String(), s.TokenExpire)

	if err != nil {
		s.Logger.Error("无法生成token", zap.Error(err))
		return nil, status.Error(codes.Internal, "")
	}

	s.Logger.Info("接收code",
		zap.String("code", req.Code))
	return &authpb.LoginResponse{
		AccessToken: tkn,
		ExpireIn:    int32(s.TokenExpire.Seconds()),
	}, nil

}
